package RedStuff;

import java.util.ArrayList;
import java.util.Iterator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import Construibles.EstBomberos;
import Excepciones.FueraDeLimites;
import Juego.Agregador;
import Juego.Jugador;
import Juego.SerializablePropia;
import Juego.SerializadorPorUbicacionEnElMapa;
import MapaStuff.Hectarea;
import MapaStuff.Mapa;
import Ubicacion.Punto;

public abstract class Red implements SerializablePropia {
	
	protected ArrayList<Fuente> fuentes;
	protected ArrayList<Conector> conectores;
	protected ArrayList<Cliente> clientes;
	
	
	public Red(){
		fuentes=new ArrayList<Fuente>();
		conectores=new ArrayList<Conector>();
		clientes=new  ArrayList<Cliente>();
	}
	
	protected void agregarFuente(Fuente fuente){
		
		fuentes.add(fuente);
		conectores.add(fuente);
		
	}
	
	protected void removerFuente(Fuente fuente){
		while(fuentes.remove(fuente));
		this.removerConector(fuente);
	}
		
			
	
	protected void agregarConector(Conector conector){
		conectores.add(conector);
	}
	
	protected void removerConector(Conector conector){
		while(conectores.remove(conector));
		
	}
	
	protected void agregarCliente(Cliente cliente){
		clientes.add(cliente);
		conectores.add(cliente);
	}
	
	protected void removerCliente(Cliente cliente){
		while(clientes.remove(cliente));
		this.removerConector(cliente);
	}

	protected Conector buscarConector(Hectarea hectarea){

		Iterator<Conector> ite= conectores.iterator();
		Conector conector;
		while(ite.hasNext()){
			conector=ite.next();
			if(conector.hectarea()==hectarea){
				return conector;
			}
		}
		return new ConectorNulo(hectarea);
		
	}
	
	protected abstract void fuenteSuministraAClintesConectados(Fuente fuente);
	
	public void suministrar(){
		Iterator<Fuente> it= fuentes.iterator();
		
		while(it.hasNext()){
			Fuente fuente=it.next();
			this.fuenteSuministraAClintesConectados(fuente);
			}
			
	}

	protected Cliente buscarCliente(Hectarea hectarea) {
		Iterator<Cliente> ite= clientes.iterator();
		Cliente cliente;
		while(ite.hasNext()){
			cliente=ite.next();
			if(cliente.hectarea()==hectarea){
				return cliente;
			}
		}
		return new ClienteNulo(hectarea);
		
	}
	
	
	public Element serializar(Document doc) {
		Element eleRed=doc.createElement("Red");
		Element eleFuentes=doc.createElement("Fuentes");
		eleRed.appendChild(eleFuentes);
		SerializadorPorUbicacionEnElMapa.serializarPorUbicacionEnElMapa(eleFuentes, doc, fuentes);
		Element eleClientes=doc.createElement("Clientes");
		eleRed.appendChild(eleClientes);
		SerializadorPorUbicacionEnElMapa.serializarPorUbicacionEnElMapa(eleClientes, doc, clientes);
		Element eleConectores=doc.createElement("Conectores");
		eleRed.appendChild(eleConectores);
		SerializadorPorUbicacionEnElMapa.serializarPorUbicacionEnElMapa(eleConectores, doc, conectores);
		return eleRed;
		
	}
	
	private static abstract class AgregadorDeRed implements Agregador{

		protected Red red;
		public AgregadorDeRed(Red red){
			this.red=red;
		}	
	}
	
	private static class AgregadorDeFuentes extends AgregadorDeRed{

		public AgregadorDeFuentes(Red red){
			super(red);
		}
		public void agregar(SerializablePropia elemento) {
			red.agregarFuente ((Fuente)elemento);
		}	
	}
	
	private static class AgregadorDeClientes extends AgregadorDeRed{

		public AgregadorDeClientes(Red red){
			super(red);
		}
		public void agregar(SerializablePropia elemento) {
			red.agregarCliente ((Cliente)elemento);
		}	
	}
	
	private static class AgregadorDeConectores extends AgregadorDeRed{

		public AgregadorDeConectores(Red red){
			super(red);
		}
		public void agregar(SerializablePropia elemento) {
			red.agregarConector ((Conector)elemento);
		}	
	}
	
	
	protected static Red hidratarElementosHeredados(Red red,Node item) {
		Element eleRed=(Element) item;
		Element eleFuente=(Element) eleRed.getChildNodes().item(0);
		SerializadorPorUbicacionEnElMapa.hidratarPorUbicacionEnElMapa(eleFuente, new AgregadorDeFuentes(red));
		Element eleCliente=(Element) eleRed.getChildNodes().item(1);
		SerializadorPorUbicacionEnElMapa.hidratarPorUbicacionEnElMapa(eleCliente,new AgregadorDeClientes(red));
		Element eleConectores=(Element) eleRed.getChildNodes().item(2);
		SerializadorPorUbicacionEnElMapa.hidratarPorUbicacionEnElMapa(eleConectores, new AgregadorDeConectores(red));
		return red;
	}
	
	public static Red hidratar(Node item){
		return (Red) SerializablePropia.hidratar(item);
	}

	
	
}
